package org.jiang.springbootdemo.demos.web.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.jiang.springbootdemo.demos.web.annotation.MainTransaction;
import org.jiang.springbootdemo.demos.web.annotation.SonTransaction;
import org.jiang.springbootdemo.demos.web.entity.Eat;
import org.jiang.springbootdemo.demos.web.entity.Play;
import org.jiang.springbootdemo.demos.web.entity.User;
import org.jiang.springbootdemo.demos.web.service.EatService;
import org.jiang.springbootdemo.demos.web.service.HelloService;
import org.jiang.springbootdemo.demos.web.service.PlayService;
import org.jiang.springbootdemo.demos.web.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Slf4j
@Service
public class HelloServiceImpl implements HelloService {

    @Autowired
    private ApplicationContext applicationContext;

    @Resource
    private UserService userService;

    @Resource
    private EatService eatService;

    @Resource
    private PlayService playService;

    @MainTransaction(2)//调用的方法中eat/play 使用@Async开启了线程, 所以参数为: 2
    @Transactional(rollbackFor = Exception.class)
//    @Transactional
    @Override
    public void enter(Integer age) {
        System.out.println("enter的线程：" + Thread.currentThread().getName());
        String name = "fsx-" + age;
        User user = new User();
        user.setName(name);
        user.setAge(age);
        userService.save(user);

        // 进来后开始吃饭（但因为吃饭比较耗时  所以放到Async异步线程里去做）
        applicationContext.getBean(HelloService.class).eat(age, Thread.currentThread());
//        applicationContext.getBean(HelloService.class).play(age, Thread.currentThread());

//        throw new RuntimeException("enter抛出运行异常");
    }

    @Transactional(rollbackFor = Exception.class)
    @SonTransaction
//    @Transactional // 因为吃饭也需要原子 所以也加上事务惊醒控制
    @Async("taskExecutor")
    @Override
    public void eat(Integer age, Thread thread) {
        System.out.println("eat的线程：" + Thread.currentThread().getName());
        String name = "eat-" + age;
        Eat eat = new Eat();
        eat.setName(name);
        eatService.save(eat);

        applicationContext.getBean(HelloService.class).play(age, thread);

        throw new RuntimeException("eat抛出运行异常");
    }

    @Transactional(rollbackFor = Exception.class)
    @SonTransaction
//    @Transactional
    @Async("taskExecutor")
    @Override
    public void play(Integer age, Thread thread) {
        System.out.println("play的线程：" + Thread.currentThread().getName());
        String name = "play-" + age;
        Play play = new Play();
        play.setName(name);
        playService.save(play);

//        throw new RuntimeException("play抛出运行异常");
    }
}

